import React, { useEffect, useRef, useState } from 'react';
import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
import { CSS2DRenderer, CSS2DObject } from 'three/examples/jsm/renderers/CSS2DRenderer';

interface CarbonData {
  label: string;
  value: number;
  color: string;
}

interface Props {
  data: CarbonData[];
  totalEmission: number;
}

const CarbonSaturnChart: React.FC<Props> = ({ data, totalEmission }) => {
  const containerRef = useRef<HTMLDivElement>(null);
  const [hoveredSegment, setHoveredSegment] = useState<CarbonData | null>(null);
  const [visibleTypes, setVisibleTypes] = useState<Set<string>>(new Set(data.map(d => d.label)));
  const rendererRef = useRef<THREE.WebGLRenderer | null>(null);
  const labelRendererRef = useRef<CSS2DRenderer | null>(null);
  const sceneRef = useRef<THREE.Scene | null>(null);
  const sphereRef = useRef<THREE.Mesh | null>(null);
  const segmentsRef = useRef<THREE.Group | null>(null);

  useEffect(() => {
    if (!containerRef.current) return;

    // 场景设置
    const scene = new THREE.Scene();
    sceneRef.current = scene;
    
    const camera = new THREE.PerspectiveCamera(75, containerRef.current.clientWidth / containerRef.current.clientHeight, 0.1, 1000);
    const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
    rendererRef.current = renderer;
    
    const labelRenderer = new CSS2DRenderer();
    labelRendererRef.current = labelRenderer;

    renderer.setSize(containerRef.current.clientWidth, containerRef.current.clientHeight);
    labelRenderer.setSize(containerRef.current.clientWidth, containerRef.current.clientHeight);
    
    containerRef.current.innerHTML = '';
    containerRef.current.appendChild(renderer.domElement);
    containerRef.current.appendChild(labelRenderer.domElement);
    labelRenderer.domElement.style.position = 'absolute';
    labelRenderer.domElement.style.top = '0';

    // 相机位置
    camera.position.z = 5;

    // 控制器
    const controls = new OrbitControls(camera, labelRenderer.domElement);
    controls.enableDamping = true;
    controls.dampingFactor = 0.05;
    controls.autoRotate = true;
    controls.autoRotateSpeed = 1;

    // 创建内球（总碳排放）
    const sphereGeometry = new THREE.SphereGeometry(1, 32, 32);
    const sphereMaterial = new THREE.MeshPhongMaterial({
      color: 0x52c41a,
      transparent: true,
      opacity: 0.3,
      emissive: 0x52c41a,
      emissiveIntensity: 0.2,
    });
    const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
    sphereRef.current = sphere;
    scene.add(sphere);

    // 创建外环（各类型占比）
    const segments = new THREE.Group();
    segmentsRef.current = segments;
    
    let startAngle = 0;
    const totalValue = data.reduce((sum, d) => sum + d.value, 0);
    
    data.forEach((item, index) => {
      const angle = (item.value / totalValue) * Math.PI * 2;
      const segmentGeometry = new THREE.RingGeometry(1.5, 2, 32, 1, startAngle, angle);
      const segmentMaterial = new THREE.MeshPhongMaterial({
        color: new THREE.Color(item.color),
        side: THREE.DoubleSide,
        transparent: true,
        opacity: visibleTypes.has(item.label) ? 1 : 0.2,
        emissive: new THREE.Color(item.color),
        emissiveIntensity: 0.2,
      });
      const segment = new THREE.Mesh(segmentGeometry, segmentMaterial);
      segment.userData = { ...item };
      segments.add(segment);
      startAngle += angle;
    });

    scene.add(segments);
    segments.rotation.x = Math.PI / 6;

    // 添加光源
    const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
    const pointLight = new THREE.PointLight(0xffffff, 1);
    pointLight.position.set(5, 5, 5);
    scene.add(ambientLight, pointLight);

    // 鼠标交互
    const raycaster = new THREE.Raycaster();
    const mouse = new THREE.Vector2();

    const onMouseMove = (event: MouseEvent) => {
      const rect = containerRef.current?.getBoundingClientRect();
      if (!rect) return;

      mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;
      mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;

      raycaster.setFromCamera(mouse, camera);
      const intersects = raycaster.intersectObjects(segments.children);

      if (intersects.length > 0) {
        const intersected = intersects[0].object;
        setHoveredSegment(intersected.userData as CarbonData);
        controls.autoRotate = false;
      } else {
        setHoveredSegment(null);
        controls.autoRotate = true;
      }
    };

    containerRef.current.addEventListener('mousemove', onMouseMove);

    // 动画循环
    let animationFrameId: number;
    const animate = () => {
      animationFrameId = requestAnimationFrame(animate);
      controls.update();
      renderer.render(scene, camera);
      labelRenderer.render(scene, camera);
    };
    animate();

    // 窗口大小调整
    const handleResize = () => {
      if (!containerRef.current) return;
      const width = containerRef.current.clientWidth;
      const height = containerRef.current.clientHeight;
      camera.aspect = width / height;
      camera.updateProjectionMatrix();
      renderer.setSize(width, height);
      labelRenderer.setSize(width, height);
    };

    window.addEventListener('resize', handleResize);

    // 清理函数
    return () => {
      window.removeEventListener('resize', handleResize);
      if (containerRef.current) {
        containerRef.current.removeEventListener('mousemove', onMouseMove);
      }
      cancelAnimationFrame(animationFrameId);
      renderer.dispose();
      renderer.forceContextLoss();
      scene.clear();
      
      // 移除 DOM 元素
      if (containerRef.current) {
        containerRef.current.innerHTML = '';
      }
    };
  }, [data, visibleTypes]);

  // 更新可见性
  useEffect(() => {
    if (!segmentsRef.current) return;
    segmentsRef.current.children.forEach((segment) => {
      const material = (segment as THREE.Mesh).material as THREE.MeshPhongMaterial;
      const userData = segment.userData as CarbonData;
      material.opacity = visibleTypes.has(userData.label) ? 1 : 0.2;
    });
  }, [visibleTypes]);

  const toggleType = (label: string) => {
    setVisibleTypes(prev => {
      const newSet = new Set(prev);
      if (newSet.has(label)) {
        newSet.delete(label);
      } else {
        newSet.add(label);
      }
      return newSet;
    });
  };

  return (
    <div style={{ position: 'relative', width: '100%', height: '300px' }}>
      <div ref={containerRef} style={{ width: '100%', height: '100%' }} />
      
      {/* 图例 */}
      <div style={{ 
        position: 'absolute', 
        right: '20px', 
        top: '20px',
        background: 'rgba(255,255,255,0.9)',
        padding: '10px',
        borderRadius: '8px',
        boxShadow: '0 2px 8px rgba(0,0,0,0.1)'
      }}>
        {data.map((item) => (
          <div 
            key={item.label}
            onClick={() => toggleType(item.label)}
            style={{ 
              cursor: 'pointer',
              opacity: visibleTypes.has(item.label) ? 1 : 0.5,
              display: 'flex',
              alignItems: 'center',
              marginBottom: '5px',
              transition: 'opacity 0.3s'
            }}
          >
            <div style={{ 
              width: '12px', 
              height: '12px', 
              backgroundColor: item.color,
              marginRight: '8px',
              borderRadius: '2px'
            }} />
            <span>{item.label}</span>
          </div>
        ))}
      </div>

      {/* 悬停提示 */}
      {hoveredSegment && (
        <div style={{
          position: 'absolute',
          left: '20px',
          top: '20px',
          background: 'rgba(255,255,255,0.9)',
          padding: '10px',
          borderRadius: '8px',
          boxShadow: '0 2px 8px rgba(0,0,0,0.1)',
          transition: 'all 0.3s'
        }}>
          <div style={{ fontWeight: 'bold', color: hoveredSegment.color }}>{hoveredSegment.label}</div>
          <div>{hoveredSegment.value.toFixed(1)} kg ({((hoveredSegment.value / totalEmission) * 100).toFixed(1)}%)</div>
        </div>
      )}
    </div>
  );
};

export default CarbonSaturnChart; 